package org.hibiscus.jdp.common.aop;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;

/**
 * Description：访问日志记录切面
 *
 * @author rannuo
 * @date 2019/1/10
 */
@Slf4j
@Aspect
@Component
public class AccessWebLogAspect {

	private ThreadLocal<Long> startTime = new ThreadLocal<>();

	@Before("accessWebLog()")
	public void doBefore(JoinPoint joinPoint) {
		startTime.set(System.currentTimeMillis());
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		assert attributes != null;
		HttpServletRequest request = attributes.getRequest();
		// 记录请求内容
		log.info("===========================================================================");
		log.info("URL : {}", request.getRequestURL());
		log.info("HTTP_METHOD : {}", request.getMethod());
		log.info("CLASS_METHOD : {}.{}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
		Enumeration<String> enu = request.getParameterNames();
		StringBuilder argsBuilder = new StringBuilder();
		while (enu.hasMoreElements()) {
			String paraName = enu.nextElement();
			argsBuilder.append(paraName).append(":").append(request.getParameter(paraName)).append("|");
		}
		String args = argsBuilder.toString();
		if (StringUtils.isNotBlank(args)) {
			log.info("ARGS : {}", args.substring(0, args.length() - 1));
		} else {
			log.info("ARGS : {}", args);
		}
	}

	@Pointcut("@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController)")
	public void accessWebLog() {
		// Only as an entry point
	}

	@AfterReturning(returning = "ret", pointcut = "accessWebLog()")
	public void doAfterReturning(Object ret) {
		// 处理完请求，记录返回内容
		log.info("RESPONSE :{} ", ret);
		log.info("SEND_TIME : {}ms", (System.currentTimeMillis() - startTime.get()));
		log.info("===========================================================================\n");
		startTime.remove();
	}

}
